using DeviceCommons.DeviceMessages.Builders;
using DeviceCommons.DeviceMessages.Enums;
using System.Text;

namespace DeviceCommons.Tests.Shared
{
    /// <summary>
    /// 测试数据构建器，提供创建各种测试场景数据的便捷方法
    /// </summary>
    public static class TestDataBuilder
    {
        /// <summary>
        /// 创建包含所有数据类型的消息构建器
        /// </summary>
        /// <param name="deviceId">设备ID</param>
        /// <returns>配置好的消息构建器</returns>
        public static DeviceMessageBuilder CreateAllDataTypesMessage(string deviceId = "AllTypesDevice")
        {
            return (DeviceMessageBuilder)DeviceMessageBuilder.Create()
                .WithHeader(version: 0x02, crcType: CRCTypeEnum.CRC16)
                .WithMainDevice(deviceId, 0x01, config =>
                {
                    config.AddReading(0, reading =>
                    {
                        reading.AddState(1, 3.14f, StateValueTypeEnum.Float32);
                        reading.AddState(2, 42, StateValueTypeEnum.Int32);
                        reading.AddState(3, "Test String", StateValueTypeEnum.String);
                        reading.AddState(4, true, StateValueTypeEnum.Bool);
                        reading.AddState(5, (ushort)123, StateValueTypeEnum.UInt16);
                        reading.AddState(6, (short)-123, StateValueTypeEnum.Int16);
                        reading.AddState(7, (ulong)1234567890, StateValueTypeEnum.Timestamp);
                        reading.AddState(8, Encoding.UTF8.GetBytes("Binary"), StateValueTypeEnum.Binary);
                        reading.AddState(9, 3.1415926535, StateValueTypeEnum.Double);
                    });
                });
        }

        /// <summary>
        /// 创建包含多个子设备的复杂消息
        /// </summary>
        /// <param name="mainDeviceId">主设备ID</param>
        /// <param name="childCount">子设备数量</param>
        /// <returns>配置好的消息构建器</returns>
        public static DeviceMessageBuilder CreateMultiChildDeviceMessage(
            string mainDeviceId = "MainDevice", 
            int childCount = 3)
        {
            var builder = (DeviceMessageBuilder)DeviceMessageBuilder.Create()
                .WithHeader(version: 0x02, crcType: CRCTypeEnum.CRC16)
                .WithMainDevice(mainDeviceId, 0x01, config =>
                {
                    config.AddReading(100, reading =>
                    {
                        reading.AddState(1, "Main Device Data", StateValueTypeEnum.String);
                    });
                });

            for (int i = 1; i <= childCount; i++)
            {
                builder.WithChildDevice($"Child{i:D2}", (byte)(0x10 + i), config =>
                {
                    config.AddReading((short)(i * 100), reading =>
                    {
                        reading.AddState(1, $"Child{i} Data", StateValueTypeEnum.String);
                        reading.AddState(2, i * 10, StateValueTypeEnum.Int32);
                    });
                });
            }

            return builder;
        }

        /// <summary>
        /// 创建大量读数的消息（用于性能测试）
        /// </summary>
        /// <param name="deviceId">设备ID</param>
        /// <param name="readingCount">读数数量</param>
        /// <param name="statesPerReading">每个读数的状态数量</param>
        /// <returns>配置好的消息构建器</returns>
        public static DeviceMessageBuilder CreateLargeDataMessage(
            string deviceId = "LargeDataDevice",
            int readingCount = 50,
            int statesPerReading = 10)
        {
            return (DeviceMessageBuilder)DeviceMessageBuilder.Create()
                .WithHeader(version: 0x02, crcType: CRCTypeEnum.CRC16)
                .WithMainDevice(deviceId, 0x01, config =>
                {
                    for (int i = 0; i < readingCount; i++)
                    {
                        config.AddReading((short)(i * 100), reading =>
                        {
                            for (int j = 1; j <= statesPerReading; j++)
                            {
                                reading.AddState((byte)j, $"Reading{i:D3}-State{j:D2}", StateValueTypeEnum.String);
                            }
                        });
                    }
                });
        }

        /// <summary>
        /// 创建可压缩的重复数据消息
        /// </summary>
        /// <param name="deviceId">设备ID</param>
        /// <param name="repeatCount">重复次数</param>
        /// <returns>配置好的消息构建器</returns>
        public static DeviceMessageBuilder CreateCompressibleMessage(
            string deviceId = "CompressibleDevice",
            int repeatCount = 10)
        {
            var repetitiveText = string.Join(" ", Enumerable.Repeat("This is repeated text for compression testing", 4));
            
            return (DeviceMessageBuilder)DeviceMessageBuilder.Create()
                .WithHeader(version: 0x02, crcType: CRCTypeEnum.CRC16)
                .WithGZipCompression()
                .WithMainDevice(deviceId, 0x01, config =>
                {
                    for (int i = 0; i < repeatCount; i++)
                    {
                        config.AddReading((short)(i * 50), reading =>
                        {
                            reading.AddState(1, repetitiveText, StateValueTypeEnum.String);
                            reading.AddState(2, repetitiveText, StateValueTypeEnum.String);
                            reading.AddState(3, $"Unique data {i}", StateValueTypeEnum.String);
                        });
                    }
                });
        }

        /// <summary>
        /// 创建用于加密测试的敏感数据消息
        /// </summary>
        /// <param name="deviceId">设备ID</param>
        /// <param name="password">加密密码</param>
        /// <returns>配置好的消息构建器</returns>
        public static IDeviceMessageBuilder CreateEncryptedMessage(
            string deviceId = "SecureDevice",
            string? password = null)
        {
            var builder = (IDeviceMessageBuilder)DeviceMessageBuilder.Create()
                .WithHeader(version: 0x02, crcType: CRCTypeEnum.CRC32);
                
            // 如果没有提供密码，则使用默认密码
            if (string.IsNullOrEmpty(password))
            {
                builder = builder.WithAesEncryption(); // 使用默认密码
            }
            else
            {
                builder = builder.WithAesEncryption(password); // 使用自定义密码
            }
            
            return builder.WithMainDevice(deviceId, 0x01, config =>
                {
                    config.AddReading(100, reading =>
                    {
                        reading.AddState(1, "Sensitive Information", StateValueTypeEnum.String);
                        reading.AddState(2, "Confidential Data", StateValueTypeEnum.String);
                        reading.AddState(3, 999.99f, StateValueTypeEnum.Float32);
                    });
                });
        }

        /// <summary>
        /// 创建边界条件测试数据
        /// </summary>
        /// <returns>包含各种边界条件的测试数据集合</returns>
        public static IEnumerable<(string Description, DeviceMessageBuilder Builder)> CreateBoundaryTestData()
        {
            // 最小有效消息
            yield return ("Minimal Message", (DeviceMessageBuilder)DeviceMessageBuilder.Create()
                .WithMainDevice("Min", 1, config =>
                {
                    config.AddReading(0, reading =>
                    {
                        reading.AddState(1, "Single", StateValueTypeEnum.String); // 改为非空字符串
                    });
                }));

            // 最大字符串长度
            yield return ("Max String Length", (DeviceMessageBuilder)DeviceMessageBuilder.Create()
                .WithMainDevice("MaxStr", 1, config =>
                {
                    config.AddReading(0, reading =>
                    {
                        reading.AddState(1, new string('A', byte.MaxValue), StateValueTypeEnum.String);
                    });
                }));

            // 负时间偏移
            yield return ("Negative Time Offset", (DeviceMessageBuilder)DeviceMessageBuilder.Create()
                .WithMainDevice("NegTime", 1, config =>
                {
                    config.AddReading(-1000, reading =>
                    {
                        reading.AddState(1, "Negative offset", StateValueTypeEnum.String);
                    });
                }));

            // 最大时间偏移
            yield return ("Max Time Offset", (DeviceMessageBuilder)DeviceMessageBuilder.Create()
                .WithMainDevice("MaxTime", 1, config =>
                {
                    config.AddReading(short.MaxValue, reading =>
                    {
                        reading.AddState(1, "Max offset", StateValueTypeEnum.String);
                    });
                }));

            // 空二进制数据
            yield return ("Empty Binary", (DeviceMessageBuilder)DeviceMessageBuilder.Create()
                .WithMainDevice("EmptyBin", 1, config =>
                {
                    config.AddReading(0, reading =>
                    {
                        reading.AddState(1, new byte[] { 0x01 }, StateValueTypeEnum.Binary); // 改为非空数组
                    });
                }));

            // 大二进制数据
            yield return ("Large Binary", (DeviceMessageBuilder)DeviceMessageBuilder.Create()
                .WithMainDevice("LargeBin", 1, config =>
                {
                    config.AddReading(0, reading =>
                    {
                        reading.AddState(1, new byte[255], StateValueTypeEnum.Binary); // 改为255字节
                    });
                }));
        }

        /// <summary>
        /// 生成随机测试数据
        /// </summary>
        /// <param name="seed">随机种子</param>
        /// <param name="deviceId">设备ID</param>
        /// <returns>随机配置的消息构建器</returns>
        public static DeviceMessageBuilder CreateRandomMessage(int seed = 12345, string deviceId = "RandomDevice")
        {
            var random = new Random(seed);
            var readingCount = random.Next(1, 10);
            
            return (DeviceMessageBuilder)DeviceMessageBuilder.Create()
                .WithHeader(version: 0x02, crcType: CRCTypeEnum.CRC16)
                .WithMainDevice(deviceId, (byte)random.Next(1, 255), config =>
                {
                    for (int i = 0; i < readingCount; i++)
                    {
                        config.AddReading((short)random.Next(-1000, 1000), reading =>
                        {
                            var stateCount = random.Next(1, 5);
                            for (int j = 1; j <= stateCount; j++)
                            {
                                var value = random.Next(0, 3) switch
                                {
                                    0 => (object)$"Random string {random.Next()}",
                                    1 => random.Next(),
                                    _ => random.NextSingle()
                                };
                                reading.AddState((byte)j, value, StateValueTypeEnum.String);
                            }
                        });
                    }
                });
        }
    }
}